#pragma once
#include<iostream>
#include<vector>
using namespace std;

template <class T>
struct HashNode
{
	T _data;
	HashNode<T>* _next;

	HashNode(const T& data)
		:_data(data)
	{

	}
};


template <class K,class T,class Hash,class KeyOfT>
class HashTable;

template <class K,class T,class Hash,class KeyOfT>
struct __HashIterator
{
	typedef HashNode<T> Node;
	typedef HashTable<K, T, Hash, KeyOfT> HT;
	typedef __HashIterator<K, T, Hash, KeyOfT> Self;

	Node* _node;
	HT* _pht;
	__HashIterator(Node* node, HT* _pht)
		:_node(node)
		,_pht(pht)
	{

	}

	T& operator*()
	{
		return _node->_data;
	}
	T* operator->()
	{
		return &_node->_data;
	}
	Self& operator++()
	{
		if (_node->_next)
		{
			_node = _node->_next;
		}
		else
		{
			Hash hash;
			KeyOfT kot;
			size_t hashi = hash(kot(_node->_data)) & _pht->_tables.size();
			hashi++;
			for (; hashi < _pht->_tables.size(); hashi++)
			{
				if (_pht->_tables[hashi])
				{
					_node = _tables[hashi];
					break;
				}
				if (hashi == _pht->_tables.size())
				{
					_node = nullptr;
				}
			}
		}
		return *this;
	}
	bool operator==(const Self& s)const
	{
		return _node == s._node;
	}
	bool operator!=(const Self& s)const
	{
		return _node != s._node;
	}
};

template <class K,class T,class Hash,class KeyOfT>
class HashTable
{
	typedef HashNode<T> Node;
	template <class K,class T,class Hash,class KeyOfT>
	friend struct __HashIterator;
public:
	typedef __HashIterator<K, T, Hash, KeyOfT> iterator;

	iterator begin()
	{
		for (size_t i = 0; i < _tables.size(); i++)
		{
			if (_tables[i])
			{
				return iterator(_tables[i], this);
			}
		}
		return end();
	}
	iterator end()
	{
		return iterator(nullptr, this);
	}
private:
	vector<Node*> _tables;
	size_t _size = 0;
};